package com.atguigu.hbse;

import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;

/**
 * Created by Smexy on 2023/4/15
 *
 *      客户端连接hbase的原理:  客户端只需要知道hbase元数据存储的zk的集群地址，就可以连上hbase。
 *
 *
 *  ①获取连接
 *          Connection:  其中既可以连接hbase的进程，还可以连接zk。
 *                       构造: ConnectionFactory
 *                       谁创建，谁负责调用close释放。
 *
 *                       创建Connection，帮你自动进行 进程的连接，元数据的缓存等等，这些信息可以被 Connection中创建的
 *                          Table:  代表一张表。 帮你增删改查。
 *                          Admin:  代表队表的DDL操作。 帮你建表，删表，改表
 *                              所共享。
 *
 *                       Connection创建费时费事，建议一个App只创建一次，在不同的线程中共享。
 *                       Table，Admin创建省时省事，建议每个方法有自己独立使用的Table和Admin对象。
 *
 *
 *  ②使用连接发送命令
 *              使用Table对单表进行增删改查。
 *                  增:  Table.put(Put x)
 *                  删:  Table.delete(Delete x)
 *                  查:  Table.get(Get g)
 *                       Table.scan(Scan x)
 *
 *              两个工具类:
 *                  Bytes:  可以把常用的类型和byte[]进行相互转换
 *                          常用类型 转 byte[]:   Bytes.toBytes(xxx);
 *                           byte[] 转 常用类型 :   Bytes.toXxx(byte []);
 *
 *                  CellUtil:  获取一个Cell中的属性。
 *                          获取一个Cell的rokkey
 *                              CellUtil.cloneRowkey(Cell c)
 *
 *
 *  ③查询，遍历结果
 *    写操作，无需返回值
 *  ④关闭连接
 *
 *  -----------------------------------
 *
 *
 */
public class HBaseUtil
{

    /*
        提供方法，可以快速构造一个put对象

        put '表','行','列族:列名','列值'
     */
    public static Put getPut(String rk,String cf,String cq,String value){

        Put put = new Put(Bytes.toBytes(rk));
        //每添加一个cell，就执行一次 Put.addColumn()操作
        put.addColumn(Bytes.toBytes(cf),Bytes.toBytes(cq),Bytes.toBytes(value));

        return put;
    }

    //根据提供的表名，返回一个Table对象
    public static Table getTable(String table) throws IOException {
        if (StringUtils.isBlank(table)){
            throw new RuntimeException("表名非法!");
        }
        return conn.getTable(TableName.valueOf(table));
    }

    //声明为静态属性
    private static Connection conn;
    //在静态代码块中赋值，静态代码块在类加载到JVM后立刻执行，仅仅执行一次
    static {
        try {
            // 读取类路径下和hadoop相关的8个配置，还会读取和hbase相关的配置文件: hbase-site.xml 和 hbase-default.xml
            // 自己定义的配置信息，放入 hbase-site.xml
            conn = ConnectionFactory.createConnection();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void close() throws IOException {
        if (conn != null){
            conn.close();
        }
    }

    public static void parseResult(Result result) {
        //获取所有的cell，一个cell是一列的一个版本
        Cell[] cells = result.rawCells();
        for (Cell cell : cells) {
            System.out.println(Bytes.toString(CellUtil.cloneRow(cell)) + "," +
                Bytes.toString(CellUtil.cloneFamily(cell)) + ":" +
                Bytes.toString(CellUtil.cloneQualifier(cell)) + "," +
                Bytes.toString(CellUtil.cloneValue(cell)) + ", ts=" +
                cell.getTimestamp());
        }
    }
}
